home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / castools.zip / MODIFYEN.C < prev    next >
Text File  |  1990-02-13  |  8KB  |  238 lines

  1.  
  2.  
  3. /*
  4.    ADDENTRY.C Function PbAddEntry:  Adds an entry (individual or group) to an
  5.       open phonebook.
  6.  
  7.    INPUT:  Phonebook structure and filled phonebook entry structure.
  8.  
  9.    OUTPUT: If successful, updates the entries field of the phonebook
  10.       structure, and sets the ID field of the entry structure.
  11. */
  12.  
  13. #include <stdio.h>
  14. #include <io.h>
  15. #include <string.h>
  16. #include <malloc.h>
  17. #include <phonebk.h>
  18.  
  19. int pascal PbModifyEntry(PB *pb, int RecordID, PBE *new_entry)
  20. {
  21.   PBE *old_entry = NULL, *group_entry = NULL;
  22.   PBEFIXED fixed_part;
  23.   char *entry_buffer;
  24.   int result;
  25.   int filenum;
  26.   int i, j;               /* loop counters */
  27.   long PbSize, offset;
  28.   BYTE hw_type,
  29.        hasccc = HASCCC;    /* for changing the h/w type of a group */
  30.   int red, writ;           /* for checking returns from fread() and fwrite() */
  31.   int buffed_rids = pb->OBufferSize/sizeof(LONGWORD);  /* whether 0 or not */
  32.   int temperrno = 0;                          /* for saving aside Pberrno */
  33.  
  34.   Pberrno = 0;                               /* Initially, always reset */
  35.  
  36.   /* First, check params */
  37.   if ((pb == NULL) ||
  38.       (new_entry == NULL)) {
  39.     Pberrno = INVALIDPARAMETER;
  40.     goto error_out;
  41.   }
  42.   if ((RecordID < 0) ||
  43.       (RecordID > 999)) {
  44.     Pberrno = INVALIDPARAMETER;
  45.     return(NULL);
  46.   }
  47.  
  48.   /* Allocate memory for and fetch the record being changed */
  49.   old_entry = PbGetEntry(pb, NULL, NULL, RecordID);
  50.   if (!old_entry) {
  51.     Pberrno = NOENTRYPRESENT;
  52.     goto error_out;
  53.   }
  54.  
  55.   /* call EntryOkToChange(); if not, free the old_entry and get out */
  56.   if ((!(entry_buffer = EntryOkToChange(pb, old_entry, new_entry)))) {
  57.     Pberrno = INVALIDCHANGE;
  58.     goto error_out;
  59.   }
  60.  
  61.   /* If new entry is larger than old, put it at end of file */
  62.   if (new_entry->length > old_entry->length) {
  63.  
  64.     /* Next, find the offset of the end-of-file , and set a vbl offset to it */
  65.     filenum = fileno(pb->fp);
  66.     PbSize = filelength(filenum);
  67.     if (PbSize == -1L) {
  68.       Pberrno = FILELENGTHERROR;
  69.       goto error_out;
  70.     }
  71.     offset = PbSize;
  72.  
  73.     /* Attempt the append to file */
  74.     if (fseek(pb->fp, 0L, SEEK_END)) {
  75.       Pberrno = FSEEKERROR;
  76.       goto error_out;
  77.     }
  78.     writ = fwrite(entry_buffer, new_entry->length, 1, pb->fp);
  79.  
  80.     if (writ != 1) {
  81.       Pberrno = CANTWRITE;
  82.       goto error_out;
  83.     }
  84.  
  85.     /* If write successful, change the offset at RID and unused_bytes field */
  86.     else {
  87.  
  88.       /* If the RID is in the OBuffer, change the offset there first */
  89.       if (pb->OBuffer) {
  90.         if ((RecordID >= pb->FirstOBufferRID) &&
  91.             (RecordID < pb->FirstOBufferRID + buffed_rids)) {
  92.           pb->OBuffer[RecordID - pb->FirstOBufferRID] = offset;
  93.         }
  94.       }
  95.  
  96.       /* Write the changed offset to the file */
  97.       if (fseek(pb->fp, 160L + RecordID*sizeof(LONGWORD), SEEK_SET)) {
  98.         Pberrno = FSEEKERROR;
  99.         goto error_out;
  100.       }
  101.       writ = fwrite(&offset, sizeof(LONGWORD), 1, pb->fp);
  102.       if (writ != 1) {
  103.         Pberrno = CANTWRITE;
  104.         goto error_out;
  105.       }
  106.  
  107.       /* Add size of old entry to the FreeBytes field */
  108.       pb->header.FreeBytes += old_entry->length;
  109.     }
  110.   }
  111.  
  112.   /* The new entry is smaller, or the same size */
  113.   else {
  114.  
  115.     /* Otherwise, just write the new entry where the old entry was */
  116.  
  117.     /* First, there is STILL a possibility of freeing too many bytes */
  118.     if ((old_entry->length - new_entry->length + pb->header.FreeBytes)
  119.         > MAXUNUSEDBYTES) {
  120.       Pberrno = TOOMANYFREEBYTES;
  121.       goto error_out;
  122.     }
  123.     else {
  124.       pb->header.FreeBytes += old_entry->length - new_entry->length;
  125.     }
  126.  
  127.     /* First, find offset of old entry */
  128.     /* no error possible, since we've gotten it already */
  129.     offset = OffsetOfEntry(pb, RecordID);
  130.  
  131.     /* ...and seek to there and write the new entry in */
  132.     if (fseek(pb->fp, offset, SEEK_SET)) {
  133.       Pberrno = FSEEKERROR;
  134.       goto error_out;
  135.     }
  136.     writ = fwrite(entry_buffer, new_entry->length, 1, pb->fp);
  137.  
  138.     /* If write not successful, free the memory used for old entry, and quit */
  139.     if (writ != 1) {
  140.       Pberrno = CANTWRITE;
  141.       goto error_out;
  142.     }
  143.   }
  144.  
  145.   /* If size changed at all, "free bytes" was updated, so write it to file */
  146.   if (old_entry->length != new_entry->length) {
  147.     if (fseek(pb->fp, 6L, SEEK_SET)) {
  148.       Pberrno = FSEEKERROR;
  149.       goto error_out;
  150.     }
  151.     writ = fwrite(&pb->header.FreeBytes, sizeof(int), 1, pb->fp);
  152.     if (writ != 1) {
  153.       Pberrno = CANTWRITE;
  154.       goto error_out;
  155.     }
  156.   }
  157.  
  158.   /* If hardware type is being changed, check out all groups that entry is a
  159.       member of:  IF change is CCP-to-FaxOnly, AND any group is CCP, change
  160.       that group to FaxOnly.  IF change is FaxOnly-to-CCP, any groups should
  161.       be FaxOnly.  (If any AREN'T, set them and set a warning.)  For any
  162.       such groups, scan their other members, looking for the first FaxOnly.
  163.       IF any found, leave the group FaxOnly.  ELSE, set it to CCP. */
  164.   if (old_entry->HardwareType != new_entry->HardwareType) {
  165.  
  166.     /* If the change is to FAXONLY, make sure all groups involved be FAXONLY */
  167.     if (new_entry->HardwareType == FAXONLY) {
  168.       for (i=0; i<new_entry->members; i++) {
  169.         if (HardwareTypeOf(pb, new_entry->MemberList[i], &offset) == HASCCC) {
  170.           if (fseek(pb->fp, offset, SEEK_SET)) {
  171.             Pberrno = FSEEKERROR;
  172.             goto error_out;
  173.           }
  174.           writ = fwrite(&new_entry->HardwareType, sizeof(BYTE), 1, pb->fp);
  175.           if (writ != 1) {
  176.             Pberrno = CANTWRITE;
  177.             goto error_out;
  178.           }
  179.         }
  180.       }
  181.     }
  182.  
  183.     /* If change is FAXONLY to HASCCC there is even MORE work to do!
  184.         Every group involved should have been FAXONLY: check all their OTHER
  185.         members.  If they are all HASCCC, then change group to HASCCC */
  186.     else {
  187.       for (i=0; i<new_entry->members; i++) {
  188.         group_entry = PbGetEntry(pb, NULL, NULL, new_entry->MemberList[i]);
  189.         for (j=0; j<group_entry->members; j++) {
  190.  
  191.           /* check all members other than ours */
  192.           if (group_entry->MemberList[j] != RecordID) {
  193.             if (HardwareTypeOf(pb,
  194.                                group_entry->MemberList[j],
  195.                                &offset) == FAXONLY) {
  196.               break;
  197.             }
  198.           }
  199.         }
  200.         if (j == group_entry->members) {  /* they were all CCP except ours */
  201.           offset = OffsetOfEntry(pb, new_entry->MemberList[i]) + 7L;
  202.           if (fseek(pb->fp, offset, SEEK_SET)) {
  203.             Pberrno = FSEEKERROR;
  204.             goto error_out;
  205.           }
  206.           writ = fwrite(&hasccc, sizeof(BYTE), 1, pb->fp);
  207.           if (writ != 1) {
  208.             Pberrno = CANTWRITE;
  209.             goto error_out;
  210.           }
  211.         }   /* end of scanning other members of group the entry is member of */
  212.       }     /* end of scanning all the group the entry is a member of */
  213.     }       /* end of if change is FAXONLY to HASCCC */
  214.   }         /* end of if hardware types differ */
  215.  
  216.   /* and if we got here without any goto, all was well! */
  217.   PbFreePBE(pb, old_entry);
  218.   free(entry_buffer);
  219.   return(SUCCESS);
  220. error_out:
  221.   if (Pberrno) {
  222.     temperrno = Pberrno;
  223.   }
  224.   if (old_entry) {
  225.     PbFreePBE(pb, old_entry);
  226.   }
  227.   if (group_entry) {
  228.     PbFreePBE(pb, group_entry);
  229.   }
  230.   if (temperrno) {
  231.     Pberrno = temperrno;
  232.   }
  233.   if (entry_buffer) {
  234.     free(entry_buffer);
  235.   }
  236.   return(FAIL);
  237. }
  238.